/*
 * SamplePlugin.Timers
 * Andy Tidball
 * 
 * Project: Black Lightning Sample Plugin
 * Copyright: GNU General Public License
 */

using System;
using BlackLightning.PluginLib;
using BlackLightning.PluginLib.Modules;

[assembly: BLModule(typeof(SamplePlugin.Timers))]

namespace SamplePlugin {
	/// <summary>
	/// An example module that works with timers.
	/// </summary>
	public class Timers : Module {
		// constants
		private const string HelpText   = @"This module implements the @timer command.";
		private const string TimerUsage = @"@timer create [id] [expirations] [interval] [offset*]
  id:          an integer ID value that will uniquely identify the new timer.
  expirations: the number of times that the timer will expire before stopping.
  interval:    the number of milliseconds between each of the timer's expirations.
  offset:      the number of milliseconds into the future before this timer starts.
@timer kill [id]
  id: the unique integer ID value of the timer to kill.";

		/// <summary>
		/// Gets a property of the module.
		/// </summary>
		/// <param name="Property">The property of the module that Black Lightning is requesting.</param>
		/// <returns>The value of the requested property, or null if this module doesn't use that property.</returns>
		public override object GetProperty(ModuleProperty Property) {
			switch (Property) {
				case ModuleProperty.HelpText:
					return HelpText;
				default:
					return null;
			}
		}

		/// <summary>
		/// Called by Black Lightning whenever it has a private message for us.
		/// </summary>
		/// <param name="Message">The private message that Black Lightning is sending to us.</param>
		public override void HandleMessage(Message Message) {
			if (Message is LoadedMessage) {
				HandleMessage_Loaded(Message as LoadedMessage);
			} else if (Message is TimerExpiredMessage) {
				HandleMessage_TimerExpired(Message as TimerExpiredMessage);
			}
		}

		/// <summary>
		/// Handles all LoadedMessages sent to us.
		/// </summary>
		/// <param name="Message">The LoadedMessage sent to us by Black Lightning.</param>
		private void HandleMessage_Loaded(LoadedMessage Message) {
			// register for the @timer command
			base.RegisterPacket(new CommandPacketFilter("@timer"));
		}

		/// <summary>
		/// Handles all TimerExpiredMessages sent to us.
		/// </summary>
		/// <param name="Message">The TimerExpiredMessage sent to us by Black Lightning.</param>
		private void HandleMessage_TimerExpired(TimerExpiredMessage Message) {
			// send a message to the user that a timer expired
			base.SendToFrontEnd("Timer Expired: " + Message.ID.ToString());
		}

		/// <summary>
		/// Called by Black Lightning whenever it has a packet for us to process.
		/// </summary>
		/// <param name="Packet">The packet that we should handle.</param>
		public override void HandlePacket(ref BLPacket Packet) {
			CommandPacket P = Packet as CommandPacket;
			P.Suppress(); // we're going to handle the packet

			// if there are no arguments, send the help text
			if (P.Arguments.Length == 0) {
				base.SendToFrontEnd(TimerUsage);
				return;
			}

			// check the arguments
			string Action = P.Arguments[0];
			if (Action.ToLower() == "create") {
				// make sure we have enough arguments
				if (P.Arguments.Length < 4) {
					base.SendToFrontEnd(TimerUsage);
					return;
				}

				// grab the ID number
				int ID;
				try {
					ID = int.Parse(P.Arguments[1]);
				} catch (FormatException) {
					base.SendToFrontEnd("Invalid ID value: " + P.Arguments[1]);
					return;
				}

				// grab the expire count
				int ExpireCount;
				try {
					ExpireCount = int.Parse(P.Arguments[2]);
				} catch (FormatException) {
					base.SendToFrontEnd("Invalid repeat value: " + P.Arguments[2]);
					return;
				}

				// grab the interval
				int Interval;
				try {
					Interval = int.Parse(P.Arguments[3]);
				} catch (FormatException) {
					base.SendToFrontEnd("Invalid interval value: " + P.Arguments[3]);
					return;
				}

				// grab the offset
				DateTime Start = DateTime.Now;
				if (P.Arguments.Length > 4) {
					try {
						int Milliseconds = int.Parse(P.Arguments[4]);
						Start = DateTime.Now + TimeSpan.FromMilliseconds(Milliseconds);
					} catch (FormatException) {
						base.SendToFrontEnd("Invalid offset value: " + P.Arguments[4]);
						return;
					}
				}

				// register a new timer
				base.RegisterTimer(ID, Start, ExpireCount, Interval);
				return;
			} else if (Action.ToLower() == "kill") {
				// grab the ID number
				int ID;
				try {
					ID = int.Parse(P.Arguments[1]);
				} catch (FormatException) {
					base.SendToFrontEnd("Invalid ID value: " + P.Arguments[1]);
					return;
				}

				// unregister the timer
				base.UnregisterTimer(ID);
				return;
			} else {
				// invalid action, send the usage
				base.SendToFrontEnd(TimerUsage);
				return;
			}
		}
	}
}
